package com.fingard.dsp.bank.directbank.zbf01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqUnifiedOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsUnifiedOrder;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import com.zhongbaofu.util.Util;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.HashMap;

public class ZBF01UnifiedOrder extends ZBF01Base {
    public RetAtsUnifiedOrder submitUnifiedOrder(ReqUnifiedOrder p_req) {
        RetAtsUnifiedOrder retAts = new RetAtsUnifiedOrder();
        retAts.rdSeq = p_req.rdSeq;

        try {
            ActSetItem actItem = getBankConfig().getActSetItemByAny(p_req.ownAct, p_req.merchantId, p_req.appId, "unifiedorder");
            if (actItem != null) {
                String mchId = actItem.merchantId;
                XmlTextWriter tmpXml = new XmlTextWriter();
                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeCommonHeaderVer1(tmpXml, p_req.rdSeq);
                writeCommonHeaderVer1(xmlWriter, p_req.rdSeq);

                /*业务代码*/
                tmpXml.writeElementString("BUSINCODE", ZBF01TransType.UNIFINEDORDER);
                xmlWriter.writeElementString("BUSINCODE", ZBF01TransType.UNIFINEDORDER);
                /*商户号*/
                if (mchId != null && !"".equals(mchId)) {
                    tmpXml.writeElementString("MERCHANTID", mchId);
                    xmlWriter.writeElementString("MERCHANTID", mchId);
                }

                /*是否批量支付*/
                tmpXml.writeElementString("IS_BATCH", "0");
                xmlWriter.writeElementString("IS_BATCH", "0");

                /*支付号  当【IS_BATCH】为【0：单笔支付】，填入支付号*/
//                tmpXml.writeElementString("POLICYID", p_req.circPaymentNo);
//                xmlWriter.writeElementString("POLICYID", p_req.circPaymentNo);
                /*支付号*/
                if (p_req.circPaymentNo != null && !"".equals(p_req.circPaymentNo)) {
                    tmpXml.writeElementString("POLICYID", p_req.circPaymentNo);
                    xmlWriter.writeElementString("POLICYID", p_req.circPaymentNo);
                }
                /*01：上海车险02：非法输入，请求会被拒绝 03：非上海车险或非车险*/
                String payinfo = "01";
                if (p_req.region != null && !"04".equals(p_req.region)) {
                    payinfo = "03";
                }
                tmpXml.writeElementString("PAYINFO", payinfo);
                xmlWriter.writeElementString("PAYINFO", payinfo);
                /*商户流水号  商户系统交易流水号，由商户生成*/
                tmpXml.writeElementString("BIZNO", p_req.rdSeq);

                xmlWriter.writeElementString("BIZNO", p_req.rdSeq);

                /*金额  单位:分*/
                String amount = StringHelper.amountMultiply100(p_req.amount);
                tmpXml.writeElementString("AMOUNT", amount);
                xmlWriter.writeElementString("AMOUNT", amount);

                /*订单有效时间  单位：分钟最短 5 分钟，最长 120 分钟，如果不填写默认为 120 分钟 */
                double diffMins = (DateHelper.getDifferMins(p_req.getTimeExpire(), p_req.getTimeStart()));
                String validateMins = "";
                if (diffMins < 5) {
                    diffMins = 5;
                } else if (diffMins > 120) {
                    diffMins = 120;
                }

                validateMins = String.valueOf(diffMins);
                if (validateMins.contains(".")) {
                    validateMins = validateMins.substring(0, validateMins.indexOf("."));
                }

                tmpXml.writeElementString("VALIDTIME", validateMins);
                xmlWriter.writeElementString("VALIDTIME", validateMins);
                /*保单号列表*/
                XElement tmpRecords = new XElement("GOODSLIST", "");

                XElement goodslist = new XElement("GOODS", "");

                /*支付号*/
                if (p_req.circPaymentNo != null && "".equals(p_req.circPaymentNo)) {
                    goodslist.addChild(new XElement("POLICYID", p_req.circPaymentNo));
                }
                /*保单号*/
                if (p_req.sourceNoteCode != null && "".equals(p_req.sourceNoteCode)) {
                    goodslist.addChild(new XElement("GOODSID", p_req.sourceNoteCode));
                }
                /*保单金额*/
                goodslist.addChild(new XElement("GOODSAMT", amount));
                tmpRecords.addChild(goodslist);

                xmlWriter.writeXElement(tmpRecords);
                tmpXml.writeXElement(tmpRecords);

                /*交易日期  yyyyMMdd*/
                String paydatetime = Format.DateTime14Format.format(p_req.getTimeStart());
                tmpXml.writeElementString("TRADE_DATE", paydatetime.substring(0, 8));
                xmlWriter.writeElementString("TRADE_DATE", paydatetime.substring(0, 8));
                /*交易时间 hhmmss*/
                tmpXml.writeElementString("TRADE_TIME", paydatetime.substring(8, 14));
                xmlWriter.writeElementString("TRADE_TIME", paydatetime.substring(8, 14));
                    /*收银台通道编码 . 收银台通道编码表
                            WECHAT 微信
                            PAYECO 易联
                            CHANPAY 畅捷
                            ONECODE 一码付
                            BAOFOO 宝付 */
                String product = "";
                String channel = "";
                if ("SubmitJSAPIOrder".equals(reqHeader.transType)) {
                    channel = "JSAPI";
                    product = "WECHAT";
                } else if ("SubmitQROrder".equals(reqHeader.transType)) {
                    //Native01：微信
                    //Native02：支付宝
                    if ("ZBFNative02".equals(p_req.reqHeader.commandCode)) {
                        channel = "C_SCANALI";
                        product = "CHANPAY";
                    } else {
                        product = "WECHAT";
                        channel = "NATIVE";
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "未实现该接口";
                    WriteBankLogLn("未实现该接口:" + reqHeader.transType);
                    return retAts;
                }

                tmpXml.writeElementString("PAY_PRODUCT", product);
                xmlWriter.writeElementString("PAY_PRODUCT", product);
                    /*支付产品编码  JSAPI 		微信微信支付
                                            NATIVE		微信扫码支付
                                            QUICK		快捷支付
                                            C_JSAPIWX	微信支付
                                            C_SCANWX    微信扫码
                                            C_SCANAL    支付宝扫码
                                            C_WAPALI    支付宝WAP支付
                                            C_WXH5 	    微信H5支付
                                            C_WXMINI    微信小程序
                                            ONECODE	    一码付扫码
                                            INSTALLMENT 信用卡分期*/
                tmpXml.writeElementString("CHANNELS", channel);
                xmlWriter.writeElementString("CHANNELS", channel);
                /*支付信息分类?述*/
                XElement channelsInfo = new XElement("CHANNELS_INFO", "");
                String appid = p_req.appId;
                if (StringHelper.isNullOrEmpty(appid)) {
                    appid = actItem.appId;
                    if (StringHelper.isNullOrEmpty(appid)) {
                        retAts.respCode = "-1";
                        retAts.respInfo = "公众号支付，AppID(应用IbbD)不可为空";
                        return retAts;
                    }
                }
                if ("WECHAT".equals(product)) {
                    channelsInfo.addChild(new XElement("APPID", appid));
                    String openid = p_req.openid;
                    if (!StringHelper.hasAnyChar(openid)) {
                        if (StringHelper.isNullOrEmpty(p_req.code)) {
                            retAts.respCode = "-1";
                            retAts.respInfo = "Code和Openid不能同时为空";
                            return retAts;
                        } else {
                            if (StringHelper.isNullOrEmpty(actItem.appSecret)) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "未配置公众号的appsecret";
                                return retAts;
                            } else {
                                //通过code获取openid
                                String[] openIdRet = getOpenid(appid, actItem.appSecret, p_req.code);
                                if ("".equals(openIdRet[0])) {
                                    openid = openIdRet[1];
                                } else {
                                    retAts.respCode = "-1";
                                    retAts.payInfoCode = FailCode.E9981;
                                    retAts.respInfo = openIdRet[1];
                                    retAts.transState = PaymentState.FAIL_Payment;
                                    return retAts;
                                }
                            }
                        }
                    }
                    if (openid != null && !"".equals(openid)) {
                        channelsInfo.addChild(new XElement("OPENID", openid));
                    }

                    channelsInfo.addChild(new XElement("TRADE_TYPE", channel));

                    channelsInfo.addChild(new XElement("FEE_TYPE", "CNY"));

                    if ("JSAPI".equals(channel)) {
                        channelsInfo.addChild(new XElement("DEVICE_INFO", "WEB"));
                    }
                    if (p_req.description != null && !"".equals(p_req.description)) {
                        channelsInfo.addChild(new XElement("BODY", p_req.description));
                    }
                } else {
                    if (p_req.memo != null && !"".equals(p_req.memo)) {
                        /*商品名称*/
                        channelsInfo.addChild(new XElement("GOODSNAME", p_req.memo));
                    }
                    if (p_req.description != null && !"".equals(p_req.description)) {
                        /*订单标题*/
                        channelsInfo.addChild(new XElement("SUBJECT", p_req.description));
                    }
                }

                /*支付信息*/
                tmpXml.writeXElement(channelsInfo);
                xmlWriter.writeXElement(channelsInfo);
                if (actItem.notifyURL != null && !"".equals(actItem.notifyURL)) {
                    /*通知结果 URL   接收支付结果通知 URL*/
                    tmpXml.writeElementString("NOTIFY_URL", actItem.notifyURL);
                    xmlWriter.writeElementString("NOTIFY_URL", actItem.notifyURL);
                }
                /*页面跳转同步返回页面路径   处理完请求后，当前页面自动跳转到商户网站里指定页面的http 路径。空则不会进行该操作*/

                if (actItem.returnURL != null && !"".equals(actItem.returnURL)) {
                    tmpXml.writeElementString("RETURN_URL", actItem.returnURL);
                    xmlWriter.writeElementString("RETURN_URL", actItem.returnURL);
                }

                if ("1".equals(p_req.realNameFlag)) {
                    String realNameMode = "04";
                    /* 00：不需要实名认证  01：江苏模式 02：深圳模式  04：上海模式 05：全国模式  */
                    if (p_req.region != null && !"".equals(p_req.region)) {
                        realNameMode = p_req.region;
                    } else {
                        if ("2".equals(p_req.realNameType)) {
                            realNameMode = "02";
                        } else if ("4".equals(p_req.realNameType)) {
                            realNameMode = "01";
                        } else {
                            realNameMode = "05";
                        }
                    }
                    tmpXml.writeElementString("REALNAMEMODE", realNameMode);
                    xmlWriter.writeElementString("REALNAMEMODE", realNameMode);
                    /*证件类型*/
                    String certType = convertCertTypeToBank(p_req.certType);
                    if (certType != null && !"".equals(certType)) {
                        tmpXml.writeElementString("CERTTYPE", certType);
                        xmlWriter.writeElementString("CERTTYPE", certType);
                    }
                    if (p_req.certNumber != null && !"".equals(p_req.certNumber)) {
                        /*证件号码 投保人证件号（实名验证用） */
                        tmpXml.writeElementString("CERTNO", p_req.certNumber);
                        xmlWriter.writeElementString("CERTNO", p_req.certNumber);
                    }
                    if (p_req.oppActName != null && !"".equals(p_req.oppActName)) {
                        /*投保人姓名（实名验证用）*/
                        tmpXml.writeElementString("PERSONNAME", p_req.oppActName);
                        xmlWriter.writeElementString("PERSONNAME", p_req.oppActName);
                    }
                    if (p_req.cellPhone != null && !"".equals(p_req.cellPhone)) {
                        /*手机号  投保人手机号*/
                        tmpXml.writeElementString("PHONE", p_req.cellPhone);
                        xmlWriter.writeElementString("PHONE", p_req.cellPhone);
                    }
                } else {
                    tmpXml.writeElementString("REALNAMEMODE", "00");
                    xmlWriter.writeElementString("REALNAMEMODE", "00");
                }
                if (p_req.attach != null && !"".equals(p_req.attach)) {
                    /*说明*/
                    tmpXml.writeElementString("REMARK", p_req.attach);
                    xmlWriter.writeElementString("REMARK", p_req.attach);
                }
                tmpXml.writeEndDocument();
                WriteBankLogLn("发送银行原始报文\r\n" + tmpXml.toXmlString());
                /*长度计算不包括 MAC 值。长度位数不足左补0*/
                String mac = Util.xorAndGenMac(tmpXml.toXmlString(), actItem.saltKey);
                xmlWriter.writeElementString("MAC", mac);
                xmlWriter.writeEndDocument();


                String lengthStr = Integer.toHexString(tmpXml.toXmlString().length());
                lengthStr = "0000".substring(0, 4 - lengthStr.length()) + lengthStr;
                String tmpStr = lengthStr.toUpperCase() + xmlWriter.toXmlString();
                String[] tmpStrRet = sendToBank(tmpStr, bankFront.getUrl("unifiedUrl"));
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    // 解析银行返回
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        /*验签*/
                        if (verifySignByRSA(tmpStrRet[1], actItem.saltKey)) {
                            String rtncode = tmpBkReader.getFirstText("/MESSAGE/MBODY/RTNCODE");
                            /*OK：成功；ER：失败；BO：中断*/
                            if ("OK".equals(rtncode)) {
                                retAts.respCode = "0";
                                String busCode = tmpBkReader.getFirstText("/MESSAGE/MBODY/BUSINCODE");
                                /*判断请求返回交易类型是否一致*/
                                if (ZBF01TransType.UNIFINEDORDER.equals(busCode)) {
                                    String transSeq = tmpBkReader.getFirstText("/MESSAGE/MBODY/BIZNO");
                                    /*判断请求返回流水号是否一致*/
                                    if (transSeq.equals(p_req.rdSeq)) {
                                        // 有最终状态才更新支付提交状态
                                        if ("SubmitQROrder".equals(p_req.reqHeader.transType)) {
                                            String qrinfo = "";
                                            String imgUrl = "";
                                            if ("WECHAT".equals(product)) {
                                                imgUrl = tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/CODE_URL");
                                            } else {
                                                imgUrl = tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/QRCODEURL");
                                            }
                                            retAts.qrType = "";
                                            retAts.qrInfo = qrinfo;
                                            retAts.qrImgUrl = imgUrl;
                                        } else if ("SubmitJSAPIOrder".equals(p_req.reqHeader.transType)) {
                                            retAts.customHashMap = new HashMap<String, String>();
                                            retAts.customHashMap.put("appId", tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/APPID"));
                                            retAts.customHashMap.put("timeStamp", tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/TIMESTAMP"));
                                            retAts.customHashMap.put("signType", tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/SIGNTYPE"));
                                            retAts.customHashMap.put("package", tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/PACKAGE"));
                                            retAts.customHashMap.put("nonceStr", tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/NONCESTR"));
                                            retAts.customHashMap.put("paySign", tmpBkReader.getFirstText("/MESSAGE/MBODY/RESP_INFO/PAYSIGN"));
                                        }


                                    } else {
                                        retAts.respCode = "-1";
                                        retAts.respInfo = "请求与返回流水号不一致";
                                        WriteBankLogLn("请求与返回流水号不一致:\r\n" + "请求流水号:" + p_req.rdSeq + "\r\n返回流水号:" + transSeq);
                                    }


                                } else {
                                    retAts.respCode = "-1";
                                    retAts.respInfo = "银行返回报文交易类型错误:" + busCode;
                                    WriteBankLogLn(retAts.respInfo);
                                }
                            } else {
                                String errMsg = tmpBkReader.getFirstText("/MESSAGE/MBODY/RTNMSG");
                                retAts.respCode = "0";
                                retAts.respInfo = errMsg;
                                retAts.transState = rtncode;
                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = "签名验证失败";
                            WriteBankLogLn("签名验证失败:" + actItem.saltKey);
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpSbMsg.toString();
                    }

                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpStrRet[1];
                }
            } else {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号[" + p_req.ownAct + "]商户配置信息";
                retAts.transState = PaymentState.FAIL;
                retAts.payInfoCode = FailCode.E9981;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }


    public RetAtsQueryOrder queryUnifiedOrder(ReqQueryOrder p_req) {
        RetAtsQueryOrder retAts = new RetAtsQueryOrder();
        retAts.rdSeq = p_req.rdSeq;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                XmlTextWriter tmpXml = new XmlTextWriter();
                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeCommonQryXml1(tmpXml);
                writeCommonQryXml1(xmlWriter);
                tmpXml.writeElementString("BUSINCODE", ZBF01TransType.COMMONQRY);//业务代码
                xmlWriter.writeElementString("BUSINCODE", ZBF01TransType.COMMONQRY);
                tmpXml.writeElementString("BIZNO", p_req.rdSeq);//商户流水号
                xmlWriter.writeElementString("BIZNO", p_req.rdSeq);
                tmpXml.writeElementString("PAYRESOURCE", actItem.goodNo);//支付产品
                xmlWriter.writeElementString("PAYRESOURCE", actItem.goodNo);
                tmpXml.writeEndDocument();
                WriteBankLogLn("发送银行原始报文\r\n" + tmpXml.toXmlString());
                /*长度计算不包括 MAC 值。长度位数不足左补0*/
                Document docLength = DocumentHelper.parseText(tmpXml.toXmlString());
                String xmlLength = String.format("%04X", docLength.asXML().length());
                String mac = Util.xorAndGenMac(docLength.asXML(), actItem.saltKey);
                xmlWriter.writeElementString("MAC", mac);
                xmlWriter.writeEndDocument();
                Element mbody = docLength.getRootElement().element("MBODY");
                mbody.addElement("MAC").setText(mac);
                String sendMsg = xmlLength + docLength.asXML();

                String[] tmpStrRet = querySend(bankFront.getUrl("qryUrl"), sendMsg, actItem);
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    // 解析银行返回
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String rtncode = tmpBkReader.getFirstText("/MESSAGE/MBODY/RETCODE");
                        if ("OK".equals(rtncode)) {
                            retAts.respCode = "0";
                            retAts.respInfo = tmpBkReader.getFirstText("/MESSAGE/MBODY/RETMSG");
                            String status = tmpBkReader.getFirstText("/MESSAGE/MBODY/TRADESTATUS");
                            if ("00".equals(status) || "02".equals(status)) {
                                retAts.transState = PaymentState.PAYING;
                            } else if ("01".equals(status)) {
                                retAts.transState = PaymentState.SUCCESS;
                            } else if ("03".equals(status)) {
                                retAts.transState = PaymentState.FAIL;
                            } else if ("04".equals(status)) {
                                retAts.transState = PaymentState.REFUND_SUCCESS;
                            } else if ("05".equals(status)) {
                                retAts.transState = PaymentState.REFUND_PAYING;
                            }
                            retAts.payInfoCode = retAts.transState;
                            retAts.outTransID = tmpBkReader.getFirstText("/MESSAGE/MBODY/PAYORDERID");
                        } else {
                            retAts.respCode = "0";
                            retAts.respInfo = tmpBkReader.getFirstText("/MESSAGE/MBODY/RETMSG");
                            retAts.transState = rtncode;
                            retAts.payInfoCode = rtncode;
                        }
                    } else {
                        retAts.respCode = "0";
                        retAts.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpStrRet[1];
                }
            } else {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号[" + p_req.ownAct + "]商户配置信息!";
                retAts.transState = PaymentState.FAIL_Payment;
                retAts.payInfoCode = FailCode.E9981;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }
}
